﻿using System;
using System.Web.Mvc;

namespace QSASPMVCApplicationCSharp.Models.Binders
{
	//
	// This file shows an example of a custom IModelBinder.  This implementation creates a Product object
	// from form post values.  Note that you typically wouldn't create a custom IModelBinder per type.  
	// Instead you'd use a more generic binder like [Bind] which would handle all of your types.  
	//

	public class ProductBinder : IModelBinder
	{
		//
		// Helper Methods
		//

		private static string Concat(string modelName, string propertyName)
		{
			return (String.IsNullOrEmpty(modelName)) ? propertyName : modelName + "." + propertyName;
		}

		private static T LookupValue<T>(ControllerContext controllerContext, string propertyName, ModelStateDictionary modelState)
		{
			var binder = ModelBinders.GetBinder(typeof(T));
			var value = binder.GetValue(controllerContext, propertyName, typeof(T), modelState);
			return (value is T) ? (T)value : default(T);
		}


		//
		// IModelBinder Member Implementation
		//

		public object GetValue(ControllerContext controllerContext, string modelName, Type modelType, ModelStateDictionary modelState)
		{
			if (controllerContext == null)
			{
				throw new ArgumentNullException("controllerContext");
			}
			if (modelType != typeof(Product))
			{
				throw new ArgumentException("This binder only works with Product models.", "modelType");
			}

			// Instantiate an product object, then bind values to each property
			var e = new Product()
			{
				ProductId = LookupValue<int>(controllerContext, Concat(null, "ProductId"), modelState),
				ProductName = LookupValue<string>(controllerContext, Concat(null, "ProductName"), modelState),
				UnitPrice = LookupValue<Decimal>(controllerContext, Concat(null, "UnitPrice"), modelState),
				ReorderLevel = LookupValue<short>(controllerContext, Concat(null, "ReorderLevel"), modelState),
				Discontinued = LookupValue<Boolean>(controllerContext, Concat(null, "Discontinued"), modelState)
			};
			return e;
		}
	}
}
